
#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BStyle>
#include <BPainter>
#include <BStyle>
#include <BFont>
#include <BMaterial>

#include "ShapePanel.h"

ShapePanel::ShapePanel(BWidget* parent) : BGroupBox(parent)
{
	this->setTitle("Shape");

	BHBoxLayout* titleLayout = new BHBoxLayout();
	{
		_foldeButton = new BButton();
		_foldeButton->setName("fold");
		_foldeButton->setCheckable(true);
		_foldeButton->setAlign(Align_Center);
		_foldeButton->setForm(Form_IconAlone);
		_foldeButton->setGraph(Graph_Minus);
		_foldeButton->setIconSize(12);

		titleLayout->addWidget(_foldeButton);
		titleLayout->addSpring();
		titleLayout->setMargin(5);
	}
	this->setLayout(titleLayout, Part_Top);

	BGridLayout* gridLayout = new BGridLayout();
	{
		BLabel* isolateLabel = new BLabel("isolate");
		_isolateCheckBox = new BCheckBox();

		BLabel* visibleLabel = new BLabel("visible");
		_visibleCheckBox = new BCheckBox();

		BLabel* lineWidthLabel = new BLabel("line-width");
		_lineWidthSpinBox = new BFloatSpinBox();

		BLabel* pointSizeLabel = new BLabel("point-size");
		_pointSizeSpinBox = new BFloatSpinBox();

		BLabel* polygonModeLabel = new BLabel("poly-mode");
		_polyModeComboBox = new BComboBox();
		_polyModeComboBox->addItem("none", Poly_None);
		_polyModeComboBox->addItem("fill", Poly_Fill);
		_polyModeComboBox->addItem("line", Poly_Line);
		_polyModeComboBox->addItem("point", Poly_Point);

		BLabel* depthOffsetLabel = new BLabel("depth-offset");
		_depthOffsetSpinBox = new BFloatSpinBox();

		gridLayout->addWidget(0, 0, isolateLabel);
		gridLayout->addWidget(0, 1, _isolateCheckBox);
		gridLayout->addWidget(1, 0, visibleLabel);
		gridLayout->addWidget(1, 1, _visibleCheckBox);
		gridLayout->addWidget(2, 0, lineWidthLabel);
		gridLayout->addWidget(2, 1, _lineWidthSpinBox);
		gridLayout->addWidget(3, 0, pointSizeLabel);
		gridLayout->addWidget(3, 1, _pointSizeSpinBox);
		gridLayout->addWidget(4, 0, polygonModeLabel);
		gridLayout->addWidget(4, 1, _polyModeComboBox);
		gridLayout->addWidget(5, 0, depthOffsetLabel);
		gridLayout->addWidget(5, 1, _depthOffsetSpinBox);
		gridLayout->setColumnPolicy(0, Policy_Preferred);
	}

	BVBoxLayout* stateLayout = new BVBoxLayout();
	{
		_lightingCheckBox = new BCheckBox("lighting");
		_cullbackCheckBox = new BCheckBox("cullback");
		_depthTestCheckBox = new BCheckBox("depth-test");
		_pointSmoothCheckBox = new BCheckBox("point-smooth");
		_lineSmoothCheckBox = new BCheckBox("line-smooth");
		_polySmoothCheckBox = new BCheckBox("poly-smooth");
		_transparentCheckBox = new BCheckBox("transparent");
		_normalizeCheckBox = new BCheckBox("normalize");

		stateLayout->addWidget(_lightingCheckBox);
		stateLayout->addWidget(_cullbackCheckBox);
		stateLayout->addWidget(_depthTestCheckBox);
		stateLayout->addWidget(_pointSmoothCheckBox);
		stateLayout->addWidget(_lineSmoothCheckBox);
		stateLayout->addWidget(_polySmoothCheckBox);
		stateLayout->addWidget(_transparentCheckBox);
		stateLayout->addWidget(_normalizeCheckBox);
	}

	BHBoxLayout* materialLayout = new BHBoxLayout();
	{
		BLabel* materialLabel = new BLabel("material");
		_materialButton = new BButton(Graph_Square_Fill);
		_materialButton->setAlign(Align_LeftCenter);
		_colorButton = new BButton(Graph_Square_Fill);

		materialLayout->addWidget(materialLabel, 0);
		materialLayout->addWidget(_materialButton);
		materialLayout->addWidget(_colorButton, 0);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(gridLayout);
	vlayout->addLayout(stateLayout);
	vlayout->addLayout(materialLayout);

	connect(this, Signal_AssetChanged, &ShapePanel::slotAssetChanged);

	connect(_foldeButton, Signal_Checked, &ShapePanel::slotFoldeButtonChecked);

	connect(_isolateCheckBox, Signal_Toggled, &ShapePanel::slotIsolateCheckBoxToggled);
	connect(_visibleCheckBox, Signal_Toggled, &ShapePanel::slotVisibleCheckBoxToggled);
	connect(_lightingCheckBox, Signal_Toggled, &ShapePanel::slotLightingToggled);
	connect(_lineWidthSpinBox, Signal_ValueEdited, &ShapePanel::slotLineWidthEdited);
	connect(_pointSizeSpinBox, Signal_ValueEdited, &ShapePanel::slotPointSizeEdited);
	connect(_polyModeComboBox, Signal_ItemClicked, &ShapePanel::slotPolygonModeToggled);
	connect(_depthOffsetSpinBox, Signal_EditFinished, &ShapePanel::slotDepthOffsetEditFinished);

	connect(_cullbackCheckBox, Signal_Toggled, &ShapePanel::slotCullbackToggled);
	connect(_depthTestCheckBox, Signal_Toggled, &ShapePanel::slotDepthTestToggled);
	connect(_pointSmoothCheckBox, Signal_Toggled, &ShapePanel::slotPointSmoothToggled);
	connect(_lineSmoothCheckBox, Signal_Toggled, &ShapePanel::slotLineSmoothToggled);
	connect(_polySmoothCheckBox, Signal_Toggled, &ShapePanel::slotPolygonSmoothToggled);
	connect(_transparentCheckBox, Signal_Toggled, &ShapePanel::slotTransparentToggled);
	connect(_normalizeCheckBox, Signal_Toggled, &ShapePanel::slotNormalizeToggled);

	connect(_materialButton, Signal_Clicked, &ShapePanel::slotMaterialButtonClicked);
	connect(_colorButton, Signal_Clicked, &ShapePanel::slotColorButtonClicked);

	this->setEnabled(false);
}
ShapePanel::~ShapePanel()
{

}

void ShapePanel::slotAssetChanged(BObject* object, const BValue& value)
{
	BShape* shape = value;
	if (_shape != shape)
	{
		if (_shape)
		{
			disconnect(_shape);
			disconnect(_material);
		}
		_shape = shape;
		if (_shape)
		{
			connect(_shape, Signal_Changed, &ShapePanel::slotShapeChanged);
			_isolateCheckBox->setChecked(shape->isolate());
			_visibleCheckBox->setChecked(shape->visible());
			_lineWidthSpinBox->setValue(_shape->lineWidth());
			_pointSizeSpinBox->setValue(_shape->pointSize());
			_polyModeComboBox->setValue(_shape->polyMode());
			_depthOffsetSpinBox->setValue(_shape->depthOffset());
			_lightingCheckBox->setChecked(_shape->lighting());
			_cullbackCheckBox->setChecked(_shape->cullback());
			_depthTestCheckBox->setChecked(_shape->depthTest());
			_pointSmoothCheckBox->setChecked(_shape->pointSmooth());
			_lineSmoothCheckBox->setChecked(_shape->lineSmooth());
			_polySmoothCheckBox->setChecked(_shape->polySmooth());
			_transparentCheckBox->setChecked(_shape->transparent());
			_material = _shape->material();
			if (_material)
			{
				connect(_material, Signal_Renamed, &ShapePanel::slotMaterialRenamed);
				connect(_material, Signal_Changed, &ShapePanel::slotMaterialChanged);
				_materialButton->setText(_material->name());
				_materialButton->setColor(_material->diffuse());
			}
			else
			{
				_materialButton->setText(BString());
				_materialButton->setColor(BColor());
			}
			_colorButton->setColor(_shape->color());
		}
		this->setEnabled(shape);
	}
}
void ShapePanel::slotFoldeButtonChecked(BObject* object, const BValue& value)
{
	bool checked = value;
	if (checked)
		_foldeButton->setGraph(Graph_Plus);
	else
		_foldeButton->setGraph(Graph_Minus);
	this->setFolded(checked);
}

void ShapePanel::slotIsolateCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_shape->setIsolate(checked);
}
void ShapePanel::slotVisibleCheckBoxToggled(BObject* object, const BValue& value)
{
	bool visible = _visibleCheckBox->checked();
	_shape->setVisible(visible);
	if (visible)
		emit("object-shown", _shape);
	else
		emit("object-hidden", _shape);
}
void ShapePanel::slotLineWidthEdited(BObject* object, const BValue& value)
{
	float lineWidth = value;
	_shape->setLineWidth(lineWidth);
	emit("change-shape", _shape);
}
void ShapePanel::slotPointSizeEdited(BObject* object, const BValue& value)
{
	float pointSize = value;
	_shape->setPointSize(pointSize);
	emit("change-shape", _shape);
}
void ShapePanel::slotPolygonModeToggled(BObject* object, const BValue& value)
{
	BComboItem* item = value;
	_shape->setPolyMode(item->value());
	emit("change-shape", _shape);
}
void ShapePanel::slotDepthOffsetEditFinished(BObject* object, const BValue& value)
{
	float offset = value;
	_shape->setDepthOffset(offset);
	emit("change-shape", _shape);
}

void ShapePanel::slotShapeChanged(BShape* shape)
{
	BMaterial* material = _shape->material();
	if (_material != material)
	{
		if (_material)
		{
			disconnect(_material);
		}
		_material = material;
		if (_material)
		{
			connect(_material, Signal_Renamed, &ShapePanel::slotMaterialRenamed);
			connect(_material, Signal_Changed, &ShapePanel::slotMaterialChanged);
		}
	}
}
void ShapePanel::slotMaterialRenamed(BMaterial* material)
{
	if (_materialButton->text() != material->name())
	{
		_materialButton->setText(material->name());
	}
}
void ShapePanel::slotMaterialChanged(BMaterial* material)
{
	_materialButton->setColor(material->diffuse());
}

void ShapePanel::slotLightingToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_shape->setLighting(checked);
	emit("change-shape", _shape);
}
void ShapePanel::slotCullbackToggled(BObject* object, const BValue& value)
{
	bool cullback = value;
	_shape->setCullback(cullback);
	emit("change-shape", _shape);
}
void ShapePanel::slotDepthTestToggled(BObject* object, const BValue& value)
{
	bool depthTest = value;
	_shape->setDepthTest(depthTest);
	emit("change-shape", _shape);
}
void ShapePanel::slotPointSmoothToggled(BObject* object, const BValue& value)
{
	bool pointSmooth = value;
	_shape->setPointSmooth(pointSmooth);
	emit("change-shape", _shape);
}
void ShapePanel::slotLineSmoothToggled(BObject* object, const BValue& value)
{
	bool lineSmooth = value;
	_shape->setLineSmooth(lineSmooth);
	emit("change-shape", _shape);
}
void ShapePanel::slotPolygonSmoothToggled(BObject* object, const BValue& value)
{
	bool polySmooth = value;
	_shape->setPolySmooth(polySmooth);
	emit("change-shape", _shape);
}
void ShapePanel::slotTransparentToggled(BObject* object, const BValue& value)
{
	bool transparent = value;
	_shape->setTransparent(transparent);
	emit("change-shape", _shape);
}
void ShapePanel::slotNormalizeToggled(BObject* object, const BValue& value)
{
	bool normalize = value;
	_shape->setNormalize(normalize);
	emit("change-shape", _shape);
}

void ShapePanel::slotMaterialButtonClicked()
{
	emit("edit-material", _shape);
}
void ShapePanel::slotColorButtonClicked()
{
	BColor color = BColorDialog::ChooseColor(this, "Choose Color for Shape", _shape->color());
	_shape->setColor(color);
	_colorButton->setColor(color);
	emit("change-shape", _shape);

}

void ShapePanel::styleEvent(const BEvent& event)
{
	BGroupBox::styleEvent(event);
	const BStyle* style = this->realStyle();
	_materialButton->setTips(style->text("tips-material"));
	_colorButton->setTips(style->text("tips-color"));
}
void ShapePanel::paintEvent(const BEvent& event)
{
	BGroupBox::paintEvent(event);
}
